/**
 * @file XXTEA_Algorithm.c
 * @brief XXTEA加密算法实现
 * @details 该文件实现了XXTEA加密算法的核心功能，包括数据转换、加密解密、HEX格式转换等
 */

#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "PLT_HEADS.h"

// 调试使能宏定义
#define DEBUG_ENABLE 0  ///< 1=启用调试输出，0=禁用调试输出

// 全局缓冲区（静态分配）
static uint8_t input_buffer[MAX_INPUT_LEN];    ///< 输入数据缓冲区
static uint32_t v_buffer[MAX_V_LEN];           ///< 转换后的长整型数组缓冲区
static uint32_t k_buffer[4];                   ///< 密钥缓冲区，固定为4个uint32_t

/**
 * @def MAX_ITERATIONS
 * @brief 最大迭代次数，防止死循环
 */
#define MAX_ITERATIONS 10000

/**
 * @brief 将字节数据转换为长整型数组（小端序）
 * @param[in] data 输入字节数据指针
 * @param[in] data_len 输入数据长度
 * @param[in] w 是否在末尾添加数据长度标志（1=添加，0=不添加）
 * @param[out] v 输出长整型数组指针
 * @param[out] out_len 输出数组长度
 * @note 该函数使用小端序字节顺序进行转换
 */
void data2long(const uint8_t *data, size_t data_len, int w, uint32_t *v, size_t *out_len) {
    size_t v_len = (data_len + 3) / 4;
    if (w) v_len++;
    
    // 边界检查
    if (v_len > MAX_V_LEN) {
        *out_len = 0;
        return;
    }
    
    memset(v, 0, v_len * sizeof(uint32_t));
    
    for (size_t i = 0; i < data_len; i++) {
        size_t idx = i / 4;
        size_t shift = (i % 4) * 8;
        v[idx] |= (uint32_t)data[i] << shift;
        
        // 定期喂狗
        if (i % 100 == 0) {
            WDT_SetReload();
        }
    }
    
    if (w) {
        v[v_len - 1] = (uint32_t)data_len;
    }
    
    *out_len = v_len;
}

/**
 * @brief 将长整型数组转换为字节数据
 * @param[in] v 输入长整型数组指针
 * @param[in] v_len 输入数组长度
 * @param[in] w 是否从末尾读取数据长度标志（1=读取，0=不读取）
 * @param[out] data 输出字节数据指针
 * @param[out] out_len 输出数据长度
 * @note 如果w=1，则使用数组最后一个元素作为原始数据长度
 */
void long2data(uint32_t *v, size_t v_len, int w, uint8_t *data, size_t *out_len) {
    size_t dl;
    if (w) {
        dl = v[v_len - 1];
    } else {
        dl = v_len * 4;
    }
    
    // 边界检查
    if (dl > MAX_INPUT_LEN - 1) {
        dl = MAX_INPUT_LEN - 1;
    }
    
    memset(data, 0, dl);
    
    for (size_t i = 0; i < dl; i++) {
        size_t idx = i >> 2;
        data[i] = (uint8_t)((v[idx] >> ((i % 4) * 8)) & 0xFF);
        
        // 定期喂狗
        if (i % 100 == 0) {
            WDT_SetReload();
        }
    }
    
    *out_len = dl;
}

/**
 * @brief 将字节数据转换为HEX字符串格式
 * @param[in] input 输入字节数据指针
 * @param[in] length 输入数据长度
 * @param[out] hex 输出HEX字符串指针
 * @note HEX字符串长度为输入数据长度的2倍，需要确保输出缓冲区足够大
 */
void toHex(const uint8_t *input, size_t length, char *hex) {
    const char hex_chars[] = "0123456789abcdef";
    
    // 边界检查
    if (length * 2 >= MAX_HEX_LEN) {
        hex[0] = '\0';
        return;
    }
    
    for (size_t i = 0; i < length; i++) {
        uint8_t byte = input[i];
        hex[i*2] = hex_chars[byte >> 4];
        hex[i*2+1] = hex_chars[byte & 0x0F];
        
        // 定期喂狗
        if (i % 100 == 0) {
            WDT_SetReload();
        }
    }
    hex[length*2] = '\0';
}

/**
 * @brief XXTEA加密核心算法
 * @param[in] data 输入明文数据指针
 * @param[in] data_len 输入数据长度
 * @param[in] key 加密密钥字符串
 * @param[out] result 输出密文数据指针
 * @param[out] result_len 输出密文长度
 * @return 无
 * @note 使用全局缓冲区进行操作，避免动态内存分配
 */
void xxtea_encrypt(const uint8_t *data, size_t data_len, const char *key, uint8_t *result, size_t *result_len) {
    size_t v_len, k_len;
    
    // 使用全局缓冲区
    data2long(data, data_len, 1, v_buffer, &v_len);
    if (v_len == 0) {
        *result = '\0';
        *result_len = 0;
        return;
    }
    
    // 密钥处理
    size_t key_len = strlen(key);
    data2long((const uint8_t *)key, key_len, 0, k_buffer, &k_len);
    if (k_len != 4) {
        *result = '\0';
        *result_len = 0;
        return;
    }
    
    int n = (int)v_len - 1;
    if (n < 1) {
        long2data(v_buffer, v_len, 0, result, result_len);
        return;
    }
    
    uint32_t z = v_buffer[n];
    uint32_t y = v_buffer[0];
    
    // 使用整数运算替代floor函数
    int q = 6 + 52 / (n + 1);
    
    uint32_t sum = 0;
    
    // 添加超时保护
    int iteration_count = 0;
    
    for (int i = 0; i < q; i++) {
        sum += DELTA;
        int e = (sum >> 2) & 3;
        
        for (int p = 0; p < n; p++) {
            y = v_buffer[p + 1];
            uint32_t mx = (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k_buffer[(p & 3) ^ e] ^ z);
            z = v_buffer[p] = (v_buffer[p] + mx) & 0xFFFFFFFF;
            
            // 检查超时
            if (iteration_count++ % 100 == 0) {
                WDT_SetReload();
                if (iteration_count > MAX_ITERATIONS) {
                    *result = '\0';
                    *result_len = 0;
                    return;
                }
            }
        }
        
        y = v_buffer[0];
        uint32_t mx = (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k_buffer[(n & 3) ^ e] ^ z);
        z = v_buffer[n] = (v_buffer[n] + mx) & 0xFFFFFFFF;
        
        // 检查超时
        if (iteration_count++ % 100 == 0) {
            WDT_SetReload();
            if (iteration_count > MAX_ITERATIONS) {
                *result = '\0';
                *result_len = 0;
                return;
            }
        }
    }
    
    long2data(v_buffer, v_len, 0, result, result_len);
}

/**
 * @brief XXTEA解密核心算法
 * @param[in] data 输入密文数据指针
 * @param[in] data_len 输入数据长度
 * @param[in] key 解密密钥字符串
 * @param[out] result 输出明文数据指针
 * @param[out] result_len 输出明文长度
 * @return 无
 * @note 解密过程是加密过程的逆运算，使用相同的密钥
 */
void xxtea_decrypt(const uint8_t *data, size_t data_len, const char *key, uint8_t *result, size_t *result_len) {
    size_t v_len, k_len;
    
    // 使用全局缓冲区
    data2long(data, data_len, 0, v_buffer, &v_len);
    if (v_len == 0) {
        *result = '\0';
        *result_len = 0;
        return;
    }
    
    // 密钥处理
    size_t key_len = strlen(key);
    data2long((const uint8_t *)key, key_len, 0, k_buffer, &k_len);
    if (k_len != 4) {
        *result = '\0';
        *result_len = 0;
        return;
    }
    
    int n = (int)v_len - 1;
    if (n < 1) {
        long2data(v_buffer, v_len, 0, result, result_len);
        return;
    }
    
    uint32_t y = v_buffer[0];
    uint32_t z = v_buffer[n];
    
    // 使用整数运算替代floor函数
    int q = 6 + 52 / (n + 1);
    uint32_t sum = q * DELTA;
    
    // 添加超时保护
    int iteration_count = 0;
    
    while (sum != 0) {
        int e = (sum >> 2) & 3;
        
        for (int p = n; p > 0; p--) {
            z = v_buffer[p - 1];
            uint32_t mx = (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k_buffer[(p & 3) ^ e] ^ z);
            y = v_buffer[p] = (v_buffer[p] - mx) & 0xFFFFFFFF;
            
            // 检查超时
            if (iteration_count++ % 100 == 0) {
                WDT_SetReload();
                if (iteration_count > MAX_ITERATIONS) {
                    *result = '\0';
                    *result_len = 0;
                    return;
                }
            }
        }
        
        z = v_buffer[n];
        uint32_t mx = (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k_buffer[(0 & 3) ^ e] ^z);
        y = v_buffer[0] = (v_buffer[0] - mx) & 0xFFFFFFFF;
        
        sum -= DELTA;
        
        // 检查超时
        if (iteration_count++ % 100 == 0) {
            WDT_SetReload();
            if (iteration_count > MAX_ITERATIONS) {
                *result = '\0';
                *result_len = 0;
                return;
            }
        }
    }
    
    // 获取原始数据长度
    size_t orig_len = v_buffer[v_len - 1];
    
    // 验证长度有效性
    if (v_len < 1 || orig_len > (v_len - 1) * 4) {
        *result = '\0';
        *result_len = 0;
        return;
    }
    
    uint8_t temp[MAX_INPUT_LEN];
    size_t temp_len;
    long2data(v_buffer, v_len, 0, temp, &temp_len);
    
    // 截取原始长度数据
    if (orig_len > MAX_INPUT_LEN - 1) {
        orig_len = MAX_INPUT_LEN - 1;
    }
    
    memcpy(result, temp, orig_len);
    *result_len = orig_len;
}

/**
 * @brief 预处理函数：将换行符替换为转义序列
 * @param[in] input 输入字符串指针
 * @param[out] output 输出处理后的字符串指针
 * @note 将单个'\n'字符替换为"\\n"两个字符，用于后续加密处理
 */
void preprocess_input(const char *input, char *output) {
    int j = 0;
    for (int i = 0; input[i] != '\0' && j < MAX_INPUT_LEN - 2; i++) {
        if (input[i] == '\n') {
            output[j++] = '\\';
            output[j++] = 'n';
        } else {
            output[j++] = input[i];
        }
        
        // 定期喂狗
        if (i % 100 == 0) {
            WDT_SetReload();
        }
    }
    output[j] = '\0';
}

/**
 * @brief 后处理函数：将转义序列还原为换行符
 * @param[in] input 输入字节数据指针
 * @param[in] input_len 输入数据长度
 * @param[out] output 输出还原后的字符串指针
 * @note 将"\\n"两个字符还原为单个'\n'字符
 */
void postprocess_output(const uint8_t *input, size_t input_len, char *output) {
    int j = 0;
    for (size_t i = 0; i < input_len && j < MAX_INPUT_LEN - 1; i++) {
        if (i < input_len - 1 && input[i] == '\\' && input[i+1] == 'n') {
            output[j++] = '\n';
            i++; // 跳过下一个字符
        } else {
            output[j++] = input[i];
        }
        
        // 定期喂狗
        if (i % 100 == 0) {
            WDT_SetReload();
        }
    }
    output[j] = '\0';
}

/**
 * @brief 主加密函数
 * @param[in] input 输入明文字符串
 * @param[in] key 加密密钥字符串
 * @param[out] hex_out 输出HEX格式密文字符串
 * @return 无
 * @note 该函数集成了预处理、加密和HEX转换功能
 */
void encrypt_message(const char *input, const char *key, char *hex_out) {
    char preprocessed[MAX_INPUT_LEN];
    preprocess_input(input, preprocessed);
    
    uint8_t encrypted[MAX_INPUT_LEN];
    size_t encrypted_len = 0;
    
    xxtea_encrypt((const uint8_t *)preprocessed, strlen(preprocessed), key, encrypted, &encrypted_len);
    
    if (encrypted_len > 0) {
        toHex(encrypted, encrypted_len, hex_out);
    } else {
        hex_out[0] = '\0';
    }
}

/**
 * @brief HEX格式解密函数
 * @param[in] hex_input 输入HEX格式密文字符串
 * @param[in] hex_len HEX字符串长度
 * @param[in] key 解密密钥字符串
 * @param[out] result 输出明文字符串
 * @return 无
 * @note 该函数处理HEX格式的密文，支持显式长度参数
 */
void decrypt_from_hex(const char *hex_input, size_t hex_len, const char *key, char *result) {
    // 验证HEX长度
    if (hex_len % 2 != 0 || hex_len == 0) {
        result[0] = '\0';
        return;
    }
    
    size_t bin_len = hex_len / 2;
    
    // 边界检查
    if (bin_len > MAX_INPUT_LEN) {
        result[0] = '\0';
        return;
    }
    
    // 将Hex转换为二进制
    for (size_t i = 0; i < bin_len; i++) {
        if (i*2+1 >= hex_len) break; // 显式边界检查
        
        char hex_byte[3] = {hex_input[i*2], hex_input[i*2+1], '\0'};
        char *endptr;
        long val = strtol(hex_byte, &endptr, 16);
        
        // 验证HEX字符有效性
        if (endptr != hex_byte + 2 || val < 0 || val > 255) {
            result[0] = '\0';
            return;
        }
        
        input_buffer[i] = (uint8_t)val;
        
        // 定期喂狗
        if (i % 100 == 0) {
            WDT_SetReload();
        }
    }
    
    uint8_t decrypted[MAX_INPUT_LEN];
    size_t decrypted_len = 0;
    
    // 解密二进制数据
    xxtea_decrypt(input_buffer, bin_len, key, decrypted, &decrypted_len);
    
    // 后处理还原原始格式
    postprocess_output(decrypted, decrypted_len, result);
}

/**
 * @brief HEX解密函数封装
 * @param[in] hex_ciphertext HEX格式密文字符串
 * @param[in] hex_len HEX字符串长度
 * @param[in] key 解密密钥字符串
 * @param[out] decrypted_output 输出解密结果字符串
 * @return 无
 */
void decrypt_hex_ciphertext(const char *hex_ciphertext, size_t hex_len, const char *key, char *decrypted_output) {
    decrypt_from_hex(hex_ciphertext, hex_len, key, decrypted_output);
}

/**
 * @brief 二进制数据解密函数
 * @param[in] ciphertext 输入密文数据指针
 * @param[in] ciphertext_len 密文数据长度
 * @param[in] key 解密密钥字符串
 * @param[out] decrypted_output 输出解密结果字符串
 * @return 无
 * @note 该函数直接处理二进制密文数据，无需HEX转换
 */
void decrypt_binary(const uint8_t *ciphertext, size_t ciphertext_len, const char *key, char *decrypted_output) {
    uint8_t decrypted[MAX_INPUT_LEN];
    size_t decrypted_len = 0;
    
    // 直接调用解密核心函数
    xxtea_decrypt(ciphertext, ciphertext_len, key, decrypted, &decrypted_len);
    
    // 后处理还原原始格式
    postprocess_output(decrypted, decrypted_len, decrypted_output);
}

/**
 * @brief 串口二进制数据解密接口函数
 * @param[out] uart0data 输出解密结果缓冲区
 * @param[in] key 解密密钥字符串
 * @param[in] ciphertext_bin 输入二进制密文数据指针
 * @param[in] ciphertext_len 密文数据长度
 * @return 成功返回0，失败返回-1
 * @note 该函数专为串口通信设计，包含完整的错误检查和调试输出
 */
int Uart0data_decrypt_binary(char *uart0data, const char *key, const uint8_t *ciphertext_bin, size_t ciphertext_len) {
    // 参数验证
    if (!uart0data || !key || !ciphertext_bin) {
        #if DEBUG_ENABLE
        UART_SendString("Error: Null pointer input\r\n");
        #endif
        return -1;
    }
    #if DEBUG_ENABLE
    UART_SendString("\r\n=== Binary Decryption Start ===\r\n");
    #endif   
    // 直接解密二进制数据
    char decrypted_result[MAX_INPUT_LEN];
    decrypt_binary(ciphertext_bin, ciphertext_len, key, decrypted_result);  
    #if DEBUG_ENABLE
    UART_SendString("Decrypted: ");
    UART_SendString(decrypted_result);
    UART_SendString("\r\n");
    #endif   
    // 安全复制结果
    size_t i;
    for (i = 0; i < MAX_INPUT_LEN - 1 && decrypted_result[i] != '\0'; i++) {
        uart0data[i] = decrypted_result[i];
    }
    uart0data[i] = '\0'; // 确保终止符
    #if DEBUG_ENABLE
    UART_SendString("=== Binary Decryption Complete ===\r\n");
    #endif 
    return 0;
}

/**
 * @brief 主解密接口函数
 * @param[out] uart0data 输出解密结果缓冲区
 * @param[in] key 解密密钥字符串
 * @param[in] ciphertext_hex 输入HEX格式密文字符串
 * @param[in] ciphertext_len 密文字符串长度
 * @return 成功返回0，失败返回-1
 * @note 该函数处理HEX格式的密文输入，适用于文本传输场景
 */
int Uart0data_decrypt(char *uart0data, const char *key, const char *ciphertext_hex, size_t ciphertext_len) {
    // 参数验证
    if (!uart0data || !key || !ciphertext_hex) {
        #if DEBUG_ENABLE
        UART_SendString("Error: Null pointer input\r\n");
        #endif 
        return -1;
    }
    #if DEBUG_ENABLE
    UART_SendString("\r\n=== Decryption Start ===\r\n");
    #endif       
    // 使用HEX格式的密文进行解密
    char decrypted_result[MAX_INPUT_LEN];
    decrypt_hex_ciphertext(ciphertext_hex, ciphertext_len, key, decrypted_result);
    #if DEBUG_ENABLE
    UART_SendString("Decrypted: ");
    UART_SendString(decrypted_result);
    UART_SendString("\r\n");
    #endif     
    // 安全复制结果
    size_t i;
    for (i = 0; i < MAX_INPUT_LEN - 1 && decrypted_result[i] != '\0'; i++) {
        uart0data[i] = decrypted_result[i];
    }
    uart0data[i] = '\0'; // 确保终止符
    #if DEBUG_ENABLE
    UART_SendString("=== Decryption Complete ===\r\n");
    #endif    
    return 0;
}

#if DEBUG_ENABLE
/**
 * @brief HEX解密测试函数
 * @return 无
 * @note 用于调试和测试HEX格式的解密功能
 */
void test_decrypt(void) {
    const char hex_input[] = "52617720646174613A200E98D46B29AA67B48CFDA0F1EE0F2FF9D02B21B856CF93ADB19F9AB3436046C597C09B81D23C68CF84A6A4423FD3DEE6B8FC9D7B0D0A4465637279707465643A20";
    size_t hex_len = strlen(hex_input); // 显式计算长度
    const char *key = "XT001122334455PT";
    char decrypted_result[MAX_INPUT_LEN];
    UART_SendByte((unsigned char)hex_len);
    #if DEBUG_ENABLE
    UART_SendString("Testing HEX decryption:\r\n");
    #endif   
    decrypt_hex_ciphertext(hex_input, hex_len, key, decrypted_result);
    #if DEBUG_ENABLE
    UART_SendString("Decrypted: ");
    UART_SendString(decrypted_result);
    UART_SendString("\r\n");
    #endif   
}

/**
 * @brief 二进制解密测试函数
 * @return 无
 * @note 用于调试和测试二进制格式的解密功能
 */
void test_binary_decrypt(void) {
    // 原始二进制测试数据（对应之前的HEX测试数据）
    const uint8_t bin_input[] = {
        0xD7, 0x02, 0xAD, 0xB2, 0xE4, 0xA5, 0x70, 0x43, 0x57, 0x31, 0xD1, 0xCA,
        0x6C, 0xDF, 0xAC, 0x54, 0xA1, 0xFC, 0x81, 0xC3, 0x60, 0xC4, 0x16, 0x56,
        0xBB, 0xAC, 0x9D, 0xA5, 0x6E, 0x55, 0x85, 0x2F, 0x03, 0xC2, 0x69, 0xA2,
        0xB6, 0x75, 0x7D, 0x80, 0x7C, 0x92, 0xA3, 0xB4, 0xBF, 0xC7, 0x51, 0x07,
        0x1C, 0xC5, 0xE1, 0x60
    };
    size_t bin_len = sizeof(bin_input);
    const char *key = "XT123456789012PT";
    char decrypted_result[MAX_INPUT_LEN];
    #if DEBUG_ENABLE
    UART_SendString("Testing BINARY decryption:\r\n");
    #endif   
    Uart0data_decrypt_binary(decrypted_result, key, bin_input, bin_len);
}
#endif